package org.springblade.modules.admin.service.suger.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.modules.admin.entity.*;
import org.springblade.modules.admin.enums.MaintainPlanContentEnum;
import org.springblade.modules.admin.enums.TaskStatusEnum;
import org.springblade.modules.admin.mapper.ElevatorMapper;
import org.springblade.modules.admin.service.BuildingService;
import org.springblade.modules.admin.service.ElevatorService;
import org.springblade.modules.admin.service.IEstateElevatorService;
import org.springblade.modules.admin.service.IMaintainPlanContentService;
import org.springblade.modules.admin.service.suger.EstateSugarService;
import org.springblade.modules.admin.vo.CheckStatisticsTrendVO;
import org.springblade.modules.admin.vo.sugar.estate.*;
import org.springblade.modules.system.entity.Dict;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IDictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zcc
 * @version 1.0
 * @date 2022/12/22 9:03
 */
@Service
public class EstateSugarServiceImpl extends BaseServiceImpl<ElevatorMapper, Elevator> implements EstateSugarService {

	@Autowired
	private ElevatorService elevatorService;

	@Autowired
	private BuildingService buildingService;

	@Autowired
	private IDictService dictService;

	@Autowired
	private IMaintainPlanContentService maintainPlanContentService;

	@Autowired
	private IEstateElevatorService estateElevatorService;

	@Override
	public BuildingStatisticVo getBuildingStatisticInfo() {
		BuildingStatisticVo buildingStatisticVo = new BuildingStatisticVo();
		List<ElevatorInfoVo> list = elevatorService.getList(null, AuthUtil.getTenantId());
		final List<Long> buildingIds = list.stream().map(ElevatorInfoVo::getBuildingId).distinct().collect(Collectors.toList());
		final List<ElevatorInfoVo> stopList = list.stream().filter(o -> o.getIsStop() == 2).collect(Collectors.toList());
		buildingStatisticVo.setElevatorCounts(list.size());
		buildingStatisticVo.setBuildingCounts(buildingIds.size());
		buildingStatisticVo.setStopElevatorCounts(stopList.size());
		buildingStatisticVo.setNoStopElevatorCounts(list.size() - Convert.toInt(stopList.size(), 0));
		Map<Long, List<ElevatorInfoVo>> listMap = list.stream().collect(Collectors.groupingBy(ElevatorInfoVo::getBuildingId));

		List<BuildingInfoVo> buildingList = new ArrayList<>(16);
		for (Long buildingId : buildingIds) {
			BuildingInfoVo buildingInfoVo = new BuildingInfoVo();
			buildingInfoVo.setBuildingId(buildingId);
			List<ElevatorInfoVo> elevatorInfoVos = listMap.get(buildingId);
			buildingInfoVo.setBuildingName(elevatorInfoVos.get(0).getBuildingName());
			buildingInfoVo.setElevatorCounts(elevatorInfoVos.size());
			BigDecimal ratio = Convert.toBigDecimal(elevatorInfoVos.size()).divide(Convert.toBigDecimal(list.size()), 3, RoundingMode.HALF_UP);
			buildingInfoVo.setRatio(ratio);
			buildingList.add(buildingInfoVo);
		}
		Collections.sort(buildingList);
		buildingStatisticVo.setList(buildingList);
		return buildingStatisticVo;
	}

	@Override
	public BuildingDetailVo getBuildingDetail(Long buildingId) {
		BuildingDetailVo buildingDetailVo = new BuildingDetailVo();
		final Building building = buildingService.selectById(buildingId);
		List<ElevatorInfoVo> list = elevatorService.getList(buildingId, AuthUtil.getTenantId());
		if (list.size() == 0) {
			throw new ServiceException("该项目下没有电梯信息");
		}
		final Map<String, List<Dict>> listMap = dictService.getList("building_type").stream().collect(Collectors.groupingBy(Dict::getDictKey));
		final String dictValue = listMap.get(Convert.toStr(building.getType(), "-1")).get(0).getDictValue();
		final List<ElevatorInfoVo> stopList = list.stream().filter(o -> o.getIsStop() == 2).collect(Collectors.toList());

		buildingDetailVo.setBuildingName(building.getName());
		buildingDetailVo.setBuildingTypeName(dictValue);
		buildingDetailVo.setElevatorCounts(list.size());
		buildingDetailVo.setStopElevatorCounts(Convert.toInt(stopList.size(), 0));
		buildingDetailVo.setNoStopElevatorCounts(list.size() - buildingDetailVo.getStopElevatorCounts());
		final List<Long> elevatorIds = list.stream().map(ElevatorInfoVo::getElevatorId).collect(Collectors.toList());
		final List<User> userList = maintainPlanContentService.getUserListByElevatorIds(elevatorIds);
		buildingDetailVo.setList(userList);
		return buildingDetailVo;
	}

	@Override
	public TlwElevatorDetail getTlwElevatorDetail() {
		TlwElevatorDetail tlwElevatorDetail = new TlwElevatorDetail();
		List<ElevatorInfoVo> list = elevatorService.getList(null, AuthUtil.getTenantId());
		List<Long> brandIds = list.stream().filter(o -> o.getBrandId() != null).map(ElevatorInfoVo::getBrandId).distinct().collect(Collectors.toList());
		final Map<Long, List<ElevatorInfoVo>> listMap = list.stream().filter(o -> o.getBrandId() != null).collect(Collectors.groupingBy(ElevatorInfoVo::getBrandId));

		List<ElevatorBrandVo> brandList = new ArrayList<>(16);
		for (Long brandId : brandIds) {
			ElevatorBrandVo elevatorBrandVo = new ElevatorBrandVo();
			elevatorBrandVo.setBrandId(brandId);
			List<ElevatorInfoVo> elevatorInfoVos = listMap.get(brandId);
			elevatorBrandVo.setElevatorCounts(elevatorInfoVos.size());
			elevatorBrandVo.setBrandName(elevatorInfoVos.get(0).getBrandName());
			BigDecimal ratio = Convert.toBigDecimal(elevatorInfoVos.size()).divide(Convert.toBigDecimal(list.size()), 3, RoundingMode.HALF_UP);
			elevatorBrandVo.setRatio(ratio);
			brandList.add(elevatorBrandVo);
		}
		Collections.sort(brandList);
		tlwElevatorDetail.setList(brandList);

		List<EstateElevator> estateElevators = estateElevatorService.findAll();

		final List<EstateElevator> collect1 = estateElevators.stream().filter(o -> o.getMaintainEndTime() != null).collect(Collectors.toList());
		final List<EstateElevator> collect2 = estateElevators.stream().filter(o -> o.getMaintainEndTime() == null).collect(Collectors.toList());
		tlwElevatorDetail.setMaintainOpenCounts(collect1.size());
		tlwElevatorDetail.setMaintainDisOpenCounts(collect2.size());
		int maintainAboutStopCounts = 0;
		int tlwAboutStopCounts = 0;

		for (EstateElevator estateElevator : collect1) {
			if (estateElevator.getMaintainEndTime() != null && Convert.toInt(DateUtil.format(estateElevator.getMaintainEndTime(),"yyyyMMdd")) >= Convert.toInt(DateUtil.format(new Date(),"yyyyMMdd"))) {
				final long day = DateUtil.betweenDay(estateElevator.getMaintainEndTime(), new Date(), true);
				if (Convert.toInt(day) <= 30) {
					maintainAboutStopCounts = maintainAboutStopCounts + 1;
				}
			}
			if (estateElevator.getTlwEndTime() != null && Convert.toInt(DateUtil.format(estateElevator.getTlwEndTime(),"yyyyMMdd")) >=Convert.toInt(DateUtil.format(new Date(),"yyyyMMdd"))) {
				final long day2 = DateUtil.betweenDay(estateElevator.getTlwEndTime(), new Date(), true);
				if (Convert.toInt(day2) <= 30) {
					tlwAboutStopCounts = tlwAboutStopCounts + 1;
				}
			}


		}
		tlwElevatorDetail.setMaintainAboutStopCounts(maintainAboutStopCounts);

		//维保业务生效状态 0-未开通, 1-待生效, 2-生效中, 3-已失效
		final List<EstateElevator> list1 = collect1.stream().filter(o -> o.getMaintainStatus() == 3).collect(Collectors.toList());
		tlwElevatorDetail.setMaintainStopCounts(list1.size());


		//梯联网的处理 0-未开通, 1-待生效, 2-生效中, 3-已失效
		final List<EstateElevator> collect3 = estateElevators.stream().filter(o -> o.getTlwEndTime() != null).collect(Collectors.toList());
		final List<EstateElevator> collect4 = estateElevators.stream().filter(o -> o.getTlwEndTime() == null).collect(Collectors.toList());
		final List<EstateElevator> list2 = collect1.stream().filter(o -> o.getTlwStatus() == 3).collect(Collectors.toList());

		tlwElevatorDetail.setTlwOpenCounts(collect3.size());
		tlwElevatorDetail.setTlwDisOpenCounts(collect4.size());
		tlwElevatorDetail.setTlwAboutStopCounts(tlwAboutStopCounts);
		tlwElevatorDetail.setTlwStopCounts(list2.size());
		return tlwElevatorDetail;
	}

	@Override
	public List<Map<String, Object>> estateSugarTodayStatus(String tenantId) {
		String[] initType = {"待开始","进行中","已完成"};
		List<Map<String,Object>> result = new ArrayList<>();
		List<Long> elevatorIds = estateElevatorService.listElevatorIdsByBuilding(tenantId);
		List<MaintainPlanContent> planContents = null;
		if(ObjectUtil.isNotEmpty(elevatorIds)){
			planContents = maintainPlanContentService.list(Wrappers.<MaintainPlanContent>lambdaQuery().eq(MaintainPlanContent::getTypeStatus, MaintainPlanContentEnum.MAINTAIN_BY.getId()).in(MaintainPlanContent::getElevatorId,elevatorIds).eq(MaintainPlanContent::getPlanDate,DateUtil.format(DateUtil.date(),"yyyy-MM-dd")));
		}
		for (String type : initType) {
			Map<String,Object> map = new HashMap<>();
			map.put("label",type);
			long value = 0;
			if(ObjectUtil.isNotEmpty(planContents)){
				if(type.equals(initType[0])){
					value = planContents.stream().filter(k -> k.getStatus().equals(TaskStatusEnum.BY_DISABLE.getStatus())).map(MaintainPlanContent::getElevatorId).distinct().count();
				}else if(type.equals(initType[1])){
					value = planContents.stream().filter(k -> !k.getStatus().equals(TaskStatusEnum.BY_DISABLE.getStatus()) && !k.getStatus().equals(TaskStatusEnum.BY_SIGN.getStatus())).map(MaintainPlanContent::getElevatorId).distinct().count();
				}else if(type.equals(initType[2])){
					value = planContents.stream().filter(k -> k.getStatus().equals(TaskStatusEnum.BY_SIGN.getStatus())).map(MaintainPlanContent::getElevatorId).distinct().count();
				}
			}
			map.put("value",value);
			result.add(map);
		}
		return result;
	}

	@Override
	public List<CheckStatisticsTrendVO> estateSugarCheckPlanStatus(Integer type, String startDate, String endDate) {
		String[] initType = {"已完成"};
		List<CheckStatisticsTrendVO> result = this.initTrendEntirety(type,DateUtil.parseDate(startDate),DateUtil.parseDate(endDate),initType);
		List<Long> elevatorIds = estateElevatorService.listElevatorIdsByBuilding(AuthUtil.getTenantId());
		if(ObjectUtil.isNotEmpty(elevatorIds)){
			List<MaintainPlanContent> planContents = maintainPlanContentService.estateSugarCheckPlanFinishStatus(startDate,endDate,elevatorIds);
			if(ObjectUtil.isNotEmpty(planContents)){
				Map<String,List<MaintainPlanContent>> dateGroup;
				if(type.equals(1)){
					// 日
					dateGroup = planContents.stream().collect(Collectors.groupingBy(t -> DateUtil.format(t.getUpdateTime(),"yyyy/M/d")));
				}else {
					// 月
					dateGroup = planContents.stream().collect(Collectors.groupingBy(t -> String.format("%s月",DateUtil.format(t.getUpdateTime(), "yyyy年M"))));
				}
				result.forEach(e -> dateGroup.forEach((k, v) -> e.getTrendData().put(k,BigDecimal.valueOf(v.size()))));
			}
		}
		return result;
	}

	@Override
	public List<Map<String, Object>> estateSugarCheckPlanTop(String tenantId) {
		return maintainPlanContentService.estateSugarCheckPlanTop(tenantId);
	}

	/**
	 * 初始化保养趋势整体数据
	 * @param type 1-近七天 2- 近六个月
	 * @param initTypeArr
	 * @return
	 */
	private List<CheckStatisticsTrendVO> initTrendEntirety(Integer type,Date startDate,Date endDate,String[] initTypeArr) {
		List<CheckStatisticsTrendVO> initList = new ArrayList<>();
		for (String initType: initTypeArr) {
			CheckStatisticsTrendVO init = new CheckStatisticsTrendVO();
			init.setType(initType);
			Map<String,Object> trendData = new LinkedHashMap<>(32);
			if(type.equals(1)){
				// 近7日
				List<DateTime> rangeDate = DateUtil.rangeToList(startDate, endDate, DateField.DAY_OF_YEAR);
				rangeDate.forEach(date -> {
					trendData.put(DateUtil.format(date, "yyyy/M/d"), BigDecimal.ZERO);
				});
			}else if(type.equals(2)){
				// 近6月
				List<DateTime> rangeDate = DateUtil.rangeToList(startDate, endDate, DateField.MONTH);
				rangeDate.forEach(date -> {
					String monthDate = String.format("%s月",DateUtil.format(date, "yyyy年M"));
					trendData.put(monthDate, BigDecimal.ZERO);
				});
			}
			init.setTrendData(trendData);
			initList.add(init);
		}
		return initList;
	}
}
